{{>licenseInfo}}
#ifndef {{prefix}}_APIROUTER_H
#define {{prefix}}_APIROUTER_H

#include <functional>
#include <QObject>
#include <QStringList>
#include <QSharedPointer>
#include <QList>
#include <QMultiMap>
#include <QRegularExpression>

#include <qhttpengine/socket.h>
#include <qhttpengine/handler.h>
#include <qhttpengine/qobjecthandler.h>

{{#apiInfo}}{{#apis}}{{#operations}}#include "{{classname}}Handler.h"
{{/operations}}{{/apis}}{{/apiInfo}}

{{#cppNamespaceDeclarations}}
namespace {{this}} {
{{/cppNamespaceDeclarations}}

class {{prefix}}ApiRequestHandler : public  QHttpEngine::QObjectHandler
{
    Q_OBJECT
Q_SIGNALS:
    void requestReceived(QHttpEngine::Socket *socket);

protected:
    virtual void process(QHttpEngine::Socket *socket, const QString &path){
        Q_UNUSED(path);

        // If the slot requires all data to be received, check to see if this is
        // already the case, otherwise, wait until the rest of it arrives
        if (socket->bytesAvailable() >= socket->contentLength()) {
            Q_EMIT requestReceived(socket);
        } else {
            connect(socket, &QHttpEngine::Socket::readChannelFinished, [this, socket]() {
                Q_EMIT requestReceived(socket);
            });
        }
    }
};

class {{prefix}}ApiRouter : public QObject
{
    Q_OBJECT
public:
    {{prefix}}ApiRouter();
    virtual ~{{prefix}}ApiRouter();

    void setUpRoutes();
    void processRequest(QHttpEngine::Socket *socket);
    {{#apiInfo}}{{#apis}}
    void set{{classname}}Handler(QSharedPointer<{{classname}}Handler> handler);{{/apis}}{{/apiInfo}}
private:
    QMap<QString, std::function<void(QHttpEngine::Socket *)>> Routes;
    QMultiMap<QString, std::function<void(QHttpEngine::Socket *)>> RoutesWithPathParam;

    bool handleRequest(QHttpEngine::Socket *socket);
    bool handleRequestAndExtractPathParam(QHttpEngine::Socket *socket);

    {{#apiInfo}}{{#apis}}
    QSharedPointer<{{classname}}Handler> m{{classname}}Handler;{{/apis}}{{/apiInfo}}
protected:
    // override this method to provide custom class derived from ApiHandler classes
    virtual void createApiHandlers();

private :
    inline QString fromQHttpEngineMethod(QHttpEngine::Socket::Method method){
        switch( method ){
            case QHttpEngine::Socket::Method::OPTIONS:
                return QStringLiteral("OPTIONS");
            case QHttpEngine::Socket::Method::GET:
                return QStringLiteral("GET");
            case QHttpEngine::Socket::Method::HEAD:
                return QStringLiteral("HEAD");
            case QHttpEngine::Socket::Method::POST:
                return QStringLiteral("POST");
            case QHttpEngine::Socket::Method::PUT:
                return QStringLiteral("PUT");
            case QHttpEngine::Socket::Method::DELETE:
                return QStringLiteral("DELETE");
            case QHttpEngine::Socket::Method::TRACE:
                return QStringLiteral("TRACE");
            case QHttpEngine::Socket::Method::CONNECT:
                return QStringLiteral("CONNECT");
        }
        return QStringLiteral("");
    }

    inline QRegularExpressionMatch getRequestMatch(QString serverTemplatePath, QString requestPath){
        QRegularExpression parExpr( R"(\{([^\/\s]+)\})" );
        serverTemplatePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
        serverTemplatePath.append("[\\/]?$");
        QRegularExpression pathExpr( serverTemplatePath );
        return pathExpr.match( requestPath );
    }

};


{{#cppNamespaceDeclarations}}
}
{{/cppNamespaceDeclarations}}

#endif // {{prefix}}_APIROUTER_H
